package com.microservice.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.microservice.api.auth.AuthServiceClient;
import com.microservice.api.common.PageResult;
import com.microservice.api.user.dto.UserInfoDTO;
import com.microservice.api.user.dto.UserProfileUpdateDTO;
import com.microservice.api.user.dto.UserRegisterDTO;
import com.microservice.api.user.dto.UserUpdateDTO;
import com.microservice.user.entity.User;
import com.microservice.user.mapper.UserMapper;
import com.microservice.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户服务实现
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private AuthServiceClient authServiceClient;
    
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    
    @Override
    public UserInfoDTO register(UserRegisterDTO registerDTO) {
        // 验证验证码（调用 auth-service 的验证接口）
        if (!StringUtils.hasText(registerDTO.getCaptcha()) || !StringUtils.hasText(registerDTO.getCaptchaKey())) {
            throw new RuntimeException("请输入验证码");
        }
        
        try {
            var verifyResult = authServiceClient.verifyCaptcha(registerDTO.getCaptchaKey(), registerDTO.getCaptcha());
            if (verifyResult == null || verifyResult.getCode() != 200) {
                throw new RuntimeException("验证码验证失败");
            }
            if (!Boolean.TRUE.equals(verifyResult.getData())) {
                throw new RuntimeException("验证码错误");
            }
        } catch (RuntimeException e) {
            // 直接抛出业务异常
            throw e;
        } catch (Exception e) {
            // Feign调用异常，记录日志并返回友好提示
            log.error("调用验证码服务失败", e);
            throw new RuntimeException("验证码服务暂时不可用，请稍后重试");
        }
        
        // 验证用户名是否已存在
        if (existsByUsername(registerDTO.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 验证邮箱是否已存在
        if (StringUtils.hasText(registerDTO.getEmail()) && existsByEmail(registerDTO.getEmail())) {
            throw new RuntimeException("邮箱已被使用");
        }
        
        // 验证手机号是否已存在
        if (StringUtils.hasText(registerDTO.getPhone()) && existsByPhone(registerDTO.getPhone())) {
            throw new RuntimeException("手机号已被使用");
        }
        
        // 验证两次密码是否一致
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new RuntimeException("两次输入的密码不一致");
        }
        
        // 创建用户
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword())); // 加密密码
        user.setNickname(StringUtils.hasText(registerDTO.getNickname()) ? 
                        registerDTO.getNickname() : registerDTO.getUsername());
        user.setEmail(registerDTO.getEmail());
        user.setPhone(registerDTO.getPhone());
        user.setCreateTime(LocalDateTime.now());
        user.setStatus(1); // 默认启用
        
        // 保存用户
        userMapper.insert(user);
        log.info("用户注册成功: {}", user.getUsername());
        
        // 为新注册用户分配默认角色（普通用户）
        try {
            userMapper.insertDefaultUserRole(user.getId());
            log.info("为用户 {} 分配默认角色成功", user.getUsername());
        } catch (Exception e) {
            log.error("为用户分配默认角色失败，用户ID: {}", user.getId(), e);
            // 不影响注册流程，只记录日志
        }
        
        // 返回用户信息
        return convertToUserInfo(user);
    }
    
    @Override
    public User getUserByUsername(String username) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, username);
        return userMapper.selectOne(wrapper);
    }
    
    @Override
    public UserInfoDTO getUserInfo(Long userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        return convertToUserInfo(user);
    }
    
    @Override
    public boolean existsByUsername(String username) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, username);
        return userMapper.selectCount(wrapper) > 0;
    }
    
    @Override
    public boolean existsByEmail(String email) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, email);
        return userMapper.selectCount(wrapper) > 0;
    }
    
    @Override
    public boolean existsByPhone(String phone) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone, phone);
        return userMapper.selectCount(wrapper) > 0;
    }
    
    @Override
    public PageResult<UserInfoDTO> pageUsers(int current, int size, String username, Integer status) {
        // 构建分页对象
        Page<User> page = new Page<>(current, size);
        
        // 构建查询条件
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(username), User::getUsername, username)
               .eq(status != null, User::getStatus, status)
               .orderByDesc(User::getCreateTime);
        
        // 执行分页查询
        Page<User> userPage = userMapper.selectPage(page, wrapper);
        
        // 转换为DTO
        List<UserInfoDTO> userInfoList = userPage.getRecords().stream()
                .map(this::convertToUserInfo)
                .collect(Collectors.toList());
        
        // 封装返回结果
        return new PageResult<>(
                userPage.getCurrent(),
                userPage.getSize(),
                userPage.getTotal(),
                userInfoList
        );
    }
    
    @Override
    public UserInfoDTO updateUser(UserUpdateDTO updateDTO) {
        // 验证用户是否存在
        User user = userMapper.selectById(updateDTO.getId());
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 记录原始状态，用于判断是否需要失效token
        Integer originalStatus = user.getStatus();
        
        // 如果要修改邮箱，检查邮箱是否被其他用户使用
        if (StringUtils.hasText(updateDTO.getEmail()) && !updateDTO.getEmail().equals(user.getEmail())) {
            LambdaQueryWrapper<User> emailWrapper = new LambdaQueryWrapper<>();
            emailWrapper.eq(User::getEmail, updateDTO.getEmail())
                       .ne(User::getId, updateDTO.getId());
            if (userMapper.selectCount(emailWrapper) > 0) {
                throw new RuntimeException("邮箱已被其他用户使用");
            }
        }
        
        // 如果要修改手机号，检查手机号是否被其他用户使用
        if (StringUtils.hasText(updateDTO.getPhone()) && !updateDTO.getPhone().equals(user.getPhone())) {
            LambdaQueryWrapper<User> phoneWrapper = new LambdaQueryWrapper<>();
            phoneWrapper.eq(User::getPhone, updateDTO.getPhone())
                       .ne(User::getId, updateDTO.getId());
            if (userMapper.selectCount(phoneWrapper) > 0) {
                throw new RuntimeException("手机号已被其他用户使用");
            }
        }
        
        // 更新用户信息
        if (StringUtils.hasText(updateDTO.getNickname())) {
            user.setNickname(updateDTO.getNickname());
        }
        if (StringUtils.hasText(updateDTO.getEmail())) {
            user.setEmail(updateDTO.getEmail());
        }
        if (StringUtils.hasText(updateDTO.getPhone())) {
            user.setPhone(updateDTO.getPhone());
        }
        if (updateDTO.getStatus() != null) {
            user.setStatus(updateDTO.getStatus());
        }
        user.setUpdateTime(LocalDateTime.now());
        
        // 保存更新
        userMapper.updateById(user);
        log.info("管理员修改用户信息成功: {}", user.getUsername());
        
        // 如果管理员将用户状态改为封禁（0），则使该用户的所有token失效，强制登出
        if (updateDTO.getStatus() != null && updateDTO.getStatus() == 0 && !Integer.valueOf(0).equals(originalStatus)) {
            try {
                authServiceClient.invalidateUserTokens(updateDTO.getId());
                log.info("用户 {} (ID:{}) 被封禁，已使其所有token失效", user.getUsername(), updateDTO.getId());
            } catch (Exception e) {
                log.error("使用户token失效失败，用户ID: {}", updateDTO.getId(), e);
                // 失败不影响用户状态更新，只记录日志
            }
        }
        
        // 返回更新后的用户信息
        return convertToUserInfo(user);
    }
    
    @Override
    public UserInfoDTO updateProfile(Long userId, UserProfileUpdateDTO profileUpdateDTO) {
        // 验证用户是否存在
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 如果要修改邮箱，检查邮箱是否被其他用户使用
        if (StringUtils.hasText(profileUpdateDTO.getEmail()) && !profileUpdateDTO.getEmail().equals(user.getEmail())) {
            LambdaQueryWrapper<User> emailWrapper = new LambdaQueryWrapper<>();
            emailWrapper.eq(User::getEmail, profileUpdateDTO.getEmail())
                       .ne(User::getId, userId);
            if (userMapper.selectCount(emailWrapper) > 0) {
                throw new RuntimeException("邮箱已被其他用户使用");
            }
        }
        
        // 如果要修改手机号，检查手机号是否被其他用户使用
        if (StringUtils.hasText(profileUpdateDTO.getPhone()) && !profileUpdateDTO.getPhone().equals(user.getPhone())) {
            LambdaQueryWrapper<User> phoneWrapper = new LambdaQueryWrapper<>();
            phoneWrapper.eq(User::getPhone, profileUpdateDTO.getPhone())
                       .ne(User::getId, userId);
            if (userMapper.selectCount(phoneWrapper) > 0) {
                throw new RuntimeException("手机号已被其他用户使用");
            }
        }
        
        // 更新个人信息（普通用户只能修改基本信息，不能修改状态等敏感字段）
        if (StringUtils.hasText(profileUpdateDTO.getNickname())) {
            user.setNickname(profileUpdateDTO.getNickname());
        }
        if (StringUtils.hasText(profileUpdateDTO.getEmail())) {
            user.setEmail(profileUpdateDTO.getEmail());
        }
        if (StringUtils.hasText(profileUpdateDTO.getPhone())) {
            user.setPhone(profileUpdateDTO.getPhone());
        }
        user.setUpdateTime(LocalDateTime.now());
        
        // 保存更新
        userMapper.updateById(user);
        log.info("用户修改个人信息成功: {}", user.getUsername());
        
        // 返回更新后的用户信息
        return convertToUserInfo(user);
    }
    
    @Override
    public java.util.Set<String> getUserRoles(Long userId) {
        // 通过UserMapper查询用户角色
        // 这里需要关联查询 user -> user_role -> role 表
        List<String> roles = userMapper.selectUserRoles(userId);
        return new java.util.HashSet<>(roles);
    }
    
    @Override
    public java.util.Set<String> getUserPermissions(Long userId) {
        // 通过UserMapper查询用户权限
        // 这里需要关联查询 user -> user_role -> role -> role_permission -> permission 表
        List<String> permissions = userMapper.selectUserPermissions(userId);
        return new java.util.HashSet<>(permissions);
    }
    
    /**
     * 转换为用户信息DTO
     */
    private UserInfoDTO convertToUserInfo(User user) {
        UserInfoDTO userInfo = new UserInfoDTO();
        BeanUtils.copyProperties(user, userInfo);
        return userInfo;
    }
}
